#include "cg_local.h"

static mapEntityData_t mapEntities[MAX_GENTITIES];
static int mapEntityCount = 0;
static int mapEntityTime = 0;
static qboolean expanded = qfalse;

extern playerInfo_t pi;

qboolean ccInitial = qtrue;

void CG_TransformToCommandMapCoord( float *coord_x, float *coord_y ) {
	*coord_x = CC_2D_X + ((*coord_x - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * CC_2D_W;
	*coord_y = CC_2D_Y + ((*coord_y - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * CC_2D_H;
}

// START	xkan, 9/19/2002
//static float automapZoom = 3.583;	// apporoximately 1.2^7
static float automapZoom = 5.159;

int CG_CurLayerForZ( int z ) {
	int curlayer = 0;

	while( z > cgs.ccLayerCeils[curlayer] && curlayer < cgs.ccLayers )
		curlayer++;

	if( curlayer == cgs.ccLayers ) {
		CG_Printf( "^3Warning: no valid command map layer for z\n" );
		curlayer = 0;
	}

	return curlayer;
}

static qboolean CG_ScissorEntIsCulled( mapEntityData_t* mEnt, mapScissor_t *scissor ) {
	if( !scissor->circular ) {
		if( mEnt->automapTransformed[0] < scissor->tl[0]
			|| mEnt->automapTransformed[0] > scissor->br[0]
			|| mEnt->automapTransformed[1] < scissor->tl[1]
			|| mEnt->automapTransformed[1] > scissor->br[1] )
			return qtrue;
	} else {
		float distSquared;
		vec2_t distVec;

		distVec[0] = mEnt->automapTransformed[0] - ( scissor->tl[0] + ( 0.5f * ( scissor->br[0] - scissor->tl[0] ) ) );
		distVec[1] = mEnt->automapTransformed[1] - ( scissor->tl[1] + ( 0.5f * ( scissor->br[1] - scissor->tl[1] ) ) );
		distSquared = distVec[0]*distVec[0] + distVec[1]*distVec[1];

		if( distSquared > Square( 0.5f * (scissor->br[0] - scissor->tl[0]) ) )
			return qtrue;
	}

	return qfalse;
}

static qboolean CG_ScissorPointIsCulled( vec2_t vec, mapScissor_t *scissor ) {
	if( !scissor->circular ) {
		if( vec[0] < scissor->tl[0]
			|| vec[0] > scissor->br[0]
			|| vec[1] < scissor->tl[1]
			|| vec[1] > scissor->br[1] )
			return qtrue;
	} else {
		float distSquared;
		vec2_t distVec;

		distVec[0] = vec[0] - ( scissor->tl[0] + ( 0.5f * ( scissor->br[0] - scissor->tl[0] ) ) );
		distVec[1] = vec[1] - ( scissor->tl[1] + ( 0.5f * ( scissor->br[1] - scissor->tl[1] ) ) );
		distSquared = distVec[0]*distVec[0] + distVec[1]*distVec[1];

		if( distSquared > Square( 0.5f * (scissor->br[0] - scissor->tl[0]) ) )
			return qtrue;
	}

	return qfalse;
}

/*
=====================================================================================
CG_TransformAutomapEntity: calculate the scaled (zoomed) yet unshifted coordinate for
each map entity within the automap
=====================================================================================
*/
void CG_TransformAutomapEntity( void )
{
	int i;

	for (i=0; i<mapEntityCount; i++) {
		mapEntityData_t* mEnt = &mapEntities[i];

		// calculate the screen coordinate of this entity for the automap, consider the zoom value
		mEnt->automapTransformed[0] = (mEnt->x - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0] * 100 * automapZoom;
		mEnt->automapTransformed[1] = (mEnt->y - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1] * 100 * automapZoom;
	}
}

void CG_AdjustAutomapZoom(int zoomIn)
{
	if (zoomIn) {
		automapZoom *= 1.2;
		if (automapZoom > 7.43)  // approximately 1.2^11
			automapZoom = 7.43;
	} else {
		automapZoom /= 1.2;
		// zoom value of 1 corresponds to the most zoomed out view. The whole map is displayed 
		// in the automap
		if ( automapZoom < 1)
			automapZoom = 1;
	}
	// recalculate the screen coordinates since the zoom changed
	CG_TransformAutomapEntity();
}
// END		xkan, 9/19/2002

void CG_ParseMapEntity( int* mapEntityCount, int* offset, team_t team ) {
	mapEntityData_t* mEnt = &mapEntities[(*mapEntityCount)];
	char buffer[16];

	trap_Argv((*offset)++, buffer, 16);
	mEnt->type = atoi(buffer);

	switch( mEnt->type ) {
		case ME_CONSTRUCT: // Gordon: these ones don't need much info
		case ME_DESTRUCT:
		case ME_DESTRUCT_2:
		case ME_COMMANDMAP_MARKER:
			break;

		case ME_TANK:
		case ME_TANK_DEAD:
			trap_Argv((*offset)++, buffer, 16);
			mEnt->x = atoi(buffer) * 128;

			trap_Argv((*offset)++, buffer, 16);
			mEnt->y = atoi(buffer) * 128;

			if( cgs.ccLayers ) {
				trap_Argv((*offset)++, buffer, 16);
				mEnt->z = atoi(buffer) * 128;
			}
			break;

		default:
			trap_Argv((*offset)++, buffer, 16);
			mEnt->x = atoi(buffer) * 128;

			trap_Argv((*offset)++, buffer, 16);
			mEnt->y = atoi(buffer) * 128;

			if( cgs.ccLayers ) {
				trap_Argv((*offset)++, buffer, 16);
				mEnt->z = atoi(buffer) * 128;
			}

			trap_Argv((*offset)++, buffer, 16);
			mEnt->yaw = atoi(buffer);
			break;
	}

	trap_Argv((*offset)++, buffer, 16);
	mEnt->data = atoi(buffer);

	mEnt->transformed[0] = (mEnt->x - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0] * CC_2D_W;
	mEnt->transformed[1] = (mEnt->y - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1] * CC_2D_H;

	mEnt->team = team;

	(*mapEntityCount)++;
}

/*
=======================
CG_ParseMapEntityInfo
=======================
*/
void CG_ParseMapEntityInfo( int axis_number, int allied_number ) {
	int i, offset;

	mapEntityCount = 0;
	mapEntityTime = cg.time;

	offset = 3;

	for( i = 0; i < axis_number; i++ ) {
		CG_ParseMapEntity( &mapEntityCount, &offset, TEAM_AXIS );
	}

	for(i = 0; i < allied_number; i++) {
		CG_ParseMapEntity( &mapEntityCount, &offset, TEAM_ALLIES );
	}

	CG_TransformAutomapEntity();
}

static qboolean gridInitDone = qfalse;
static vec2_t gridStartCoord, gridStep;

static void CG_DrawGrid( float x, float y, float w, float h, mapScissor_t *scissor ) {
	vec2_t step;
	vec2_t dim_x, dim_y;
	vec4_t line;
	float xscale, yscale;
	float grid_x, grid_y;
	vec2_t dist;
	vec4_t gridColour;

	dist[0] = cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0];
	dist[1] = cg.mapcoordsMaxs[1] - cg.mapcoordsMins[1];

	if( !gridInitDone ) {
		gridStep[0] = 1200.f;
		gridStep[1] = 1200.f;

		// ensure minimal grid density
		while( ( cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0] ) / gridStep[0] < 7 )
			gridStep[0] -= 50.f;
		while( ( cg.mapcoordsMins[1] - cg.mapcoordsMaxs[1] ) / gridStep[1] < 7 )
			gridStep[1] -= 50.f;

		gridStartCoord[0] = .5f * ( ( ( ( cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0] ) / gridStep[0] ) - ( (int)(( cg.mapcoordsMaxs[0] - cg.mapcoordsMins[0] ) / gridStep[0] ) ) ) * gridStep[0] );
		gridStartCoord[1] = .5f * ( ( ( ( cg.mapcoordsMins[1] - cg.mapcoordsMaxs[1] ) / gridStep[1] ) - ( (int)(( cg.mapcoordsMins[1] - cg.mapcoordsMaxs[1] ) / gridStep[1] ) ) ) * gridStep[1] );

		gridInitDone = qtrue;
	}

	if( scissor ) {
		dim_x[0] = cg.mapcoordsMins[0];
		dim_x[1] = cg.mapcoordsMaxs[0];

		dim_y[0] = cg.mapcoordsMaxs[1];
		dim_y[1] = cg.mapcoordsMins[1];

		// transform
		xscale = ( w * scissor->zoomFactor ) / dist[0];
		yscale = ( h * scissor->zoomFactor ) / -dist[1];

		dim_x[0] = (dim_x[0] - cg.mapcoordsMins[0]) * xscale;
		dim_x[1] = (dim_x[1] - cg.mapcoordsMins[0]) * xscale;

		dim_y[0] = (dim_y[0] - cg.mapcoordsMaxs[1]) * yscale;
		dim_y[1] = (dim_y[1] - cg.mapcoordsMaxs[1]) * yscale;

		grid_x = ((gridStartCoord[0] / dist[0]) * w * scissor->zoomFactor) - scissor->tl[0];
		grid_y = ((-gridStartCoord[1] / dist[1]) * h * scissor->zoomFactor) - scissor->tl[1];

		step[0] = gridStep[0] * xscale;
		step[1] = gridStep[1] * yscale;

		// draw
		Vector4Set( gridColour, clrBrownLine[0], clrBrownLine[1], clrBrownLine[2], .4f );
		trap_R_SetColor( gridColour );
		for( ; grid_x < dim_x[1]; grid_x += step[0] )
		{
			if( grid_x < dim_x[0] )
				continue;

			if( grid_x > w )
				break;

			if( scissor->circular ) {
				// clip line against circle
				float xc, yc;

				line[0] = x + grid_x;
				xc = line[0] >= x + .5f * w ? line[0] - (x + .5f * w) : (x + .5f * w) - line[0];
				yc = SQRTFAST( Square(.5f * w) - Square(xc) );
				line[1] = y + (.5f * h) - yc;
				line[2] = 1.f;
				line[3] = 2 * yc;
			} else {
				Vector4Set( line, x + grid_x, y + dim_y[0], 1.f, h );
			}
			line[0] *= cgs.screenXScale;
			line[1] *= cgs.screenYScale;
			line[3] *= cgs.screenYScale;
			trap_R_DrawStretchPic( line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader );
		}

		for( ; grid_y < dim_y[1]; grid_y += step[1] )
		{
			if( grid_y < dim_y[0] )
				continue;

			if( grid_y > h )
				break;

			if( scissor->circular ) {
				// clip line against circle
				float xc, yc;

				line[1] = y + grid_y;
				yc = line[1] >= y + .5f * h ? line[1] - (y + .5f * h) : (y + .5f * h) - line[1];
				xc = SQRTFAST( Square(.5f * h) - Square(yc) );
				line[0] = x + (.5f * w) - xc;
				line[2] = 2 * xc;
				line[3] = 1.f;
			} else {
				Vector4Set( line, x + dim_x[0], y + grid_y, w, 1 );
			}			
			line[0] *= cgs.screenXScale;
			line[1] *= cgs.screenYScale;
			line[2] *= cgs.screenXScale;
			trap_R_DrawStretchPic( line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader );
		}
		trap_R_SetColor( NULL );
	} else {
		char coord_char[3], coord_int;
		float text_width, text_height;
		vec2_t textOrigin;

		dim_x[0] = cg.mapcoordsMins[0];
		dim_x[1] = cg.mapcoordsMaxs[0];

		dim_y[0] = cg.mapcoordsMaxs[1];
		dim_y[1] = cg.mapcoordsMins[1];

		// transform
		xscale = w / dist[0];
		yscale = h / -dist[1];

		dim_x[0] = (dim_x[0] - cg.mapcoordsMins[0]) * xscale;
		dim_x[1] = (dim_x[1] - cg.mapcoordsMins[0]) * xscale;

		dim_y[0] = (dim_y[0] - cg.mapcoordsMaxs[1]) * yscale;
		dim_y[1] = (dim_y[1] - cg.mapcoordsMaxs[1]) * yscale;

		grid_x = gridStartCoord[0] * xscale;
		grid_y = gridStartCoord[1] * yscale;

		step[0] = gridStep[0] * xscale;
		step[1] = gridStep[1] * yscale;

		// draw
		textOrigin[0] = grid_x;
		textOrigin[1] = grid_y;

		Vector4Set( gridColour, clrBrownLine[0], clrBrownLine[1], clrBrownLine[2], 1.f );

		coord_char[1] = '\0';
		for( coord_char[0] = ('A' - 1); grid_x < dim_x[1]; grid_x += step[0], coord_char[0]++ )
		{
			if( coord_char[0] >= 'A' ) {
				text_width = CG_Text_Width_Ext( coord_char, 0.2f, 0, &cgs.media.limboFont2 );
				text_height = CG_Text_Height_Ext( coord_char, 0.2f, 0, &cgs.media.limboFont2 );
				CG_Text_Paint_Ext( ( x + grid_x ) - (.5f * step[0]) - (.5f * text_width), y + dim_y[0] + textOrigin[1] + 1.5f * text_height, 0.2f, 0.2f, colorBlack, coord_char, 0, 0, 0, &cgs.media.limboFont2 );
			}
			trap_R_SetColor( gridColour );

			Vector4Set( line, x + grid_x, y + dim_y[0], 1, dim_x[1] - dim_x[0] );
			line[0] *= cgs.screenXScale;
			line[1] *= cgs.screenYScale;
			line[3] *= cgs.screenYScale;
			trap_R_DrawStretchPic( line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader );
		}

		for( coord_int = -1; grid_y < dim_y[1]; grid_y += step[1], coord_int++ )
		{
			if( coord_int >= 0 ) {
				Com_sprintf( coord_char, sizeof(coord_char), "%i", coord_int );
				text_width = CG_Text_Width_Ext( "0", 0.2f, 0, &cgs.media.limboFont2 );
				text_height = CG_Text_Height_Ext( coord_char, 0.2f, 0, &cgs.media.limboFont2 );
				CG_Text_Paint_Ext( x + dim_x[0] + textOrigin[0] + .5f * text_width, (y + grid_y) - (.5f * step[1]) + (.5f * text_height), 0.2f, 0.2f, colorBlack, coord_char, 0, 0, 0, &cgs.media.limboFont2 );
			}
			trap_R_SetColor( gridColour );

			Vector4Set( line, x + dim_x[0], y + grid_y, dim_y[1] - dim_y[0], 1 );
			line[0] *= cgs.screenXScale;
			line[1] *= cgs.screenYScale;
			line[2] *= cgs.screenXScale;
			trap_R_DrawStretchPic( line[0], line[1], line[2], line[3], 0, 0, 0, 1, cgs.media.whiteShader );
		}
		trap_R_SetColor( NULL );
	}
}


#define COMMANDMAP_PLAYER_ICON_SIZE 6
#define AUTOMAP_PLAYER_ICON_SIZE 5

// xkan: extracted from CG_DrawCommandMap.
// drawingCommandMap - qfalse: command map; qtrue: auto map (upper left in main game view)

void CG_DrawMapEntity( mapEntityData_t *mEnt, float x, float y, float w, float h, int mEntFilter, mapScissor_t *scissor, qboolean interactive, snapshot_t* snap, int icon_size ) {
	int j = 1;
	qhandle_t pic;
	clientInfo_t* ci;
	bg_playerclass_t* classInfo;
	centity_t *cent;
	const char* name;
	vec4_t c_clr = {1.f, 1.f, 1.f, 1.f};
	vec2_t icon_extends, icon_pos, string_pos;
	int customimage = 0;
	oidInfo_t* oidInfo = NULL;

	switch( mEnt->type ) {
	case ME_PLAYER_DISGUISED:
	case ME_PLAYER_REVIVE:
	case ME_PLAYER:
		ci = &cgs.clientinfo[mEnt->data];
		if(!ci->infoValid) {
			return;
		}

		if(ci->team == TEAM_AXIS) {
			if(mEntFilter & CC_FILTER_AXIS) {
				return;
			}
		} else if(ci->team == TEAM_ALLIES) {
			if(mEntFilter & CC_FILTER_ALLIES) {
				return;
			}
		} else {
			return;
		}

		cent = &cg_entities[mEnt->data];

		if( mEnt->type == ME_PLAYER_DISGUISED && !(cent->currentState.powerups & (1 << PW_OPS_DISGUISED)) ) {
			return;
		}

		classInfo = CG_PlayerClassForClientinfo(ci, cent);

		// For these, if availaible, ignore the coordinate data and grab the most up to date pvs data
		if( cent-cg_entities == cg.clientNum ) {
			if( !scissor ) {
				mEnt->transformed[0] = ((cg.predictedPlayerEntity.lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w;
				mEnt->transformed[1] = ((cg.predictedPlayerEntity.lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h;
			} else {
				mEnt->automapTransformed[0] = ((cg.predictedPlayerEntity.lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w * scissor->zoomFactor;
				mEnt->automapTransformed[1] = ((cg.predictedPlayerEntity.lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h * scissor->zoomFactor;
			}
			
			mEnt->yaw = cg.predictedPlayerState.viewangles[YAW];
		} else if( ci->team == snap->ps.persistant[PERS_TEAM] && cent->currentValid ) {
			if( !scissor ) {
				mEnt->transformed[0] = ((cent->lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w;
				mEnt->transformed[1] = ((cent->lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h;
			} else {
				mEnt->automapTransformed[0] = ((cent->lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w * scissor->zoomFactor;
				mEnt->automapTransformed[1] = ((cent->lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h * scissor->zoomFactor;
			}

			mEnt->yaw = cent->lerpAngles[YAW];
		} else {
			// Gordon: only see revivables for own team, duh :)
			if(mEnt->type == ME_PLAYER_REVIVE) {
				return;
			}
		}


		// now check to see if the entity is within our clip region
		if( scissor && CG_ScissorEntIsCulled( mEnt, scissor ) ) {
			return;
		}

		if( cgs.ccLayers ) {
			if( CG_CurLayerForZ( mEnt->z ) != cgs.ccSelectedLayer )
                return;
		}

		if( scissor ) {
			icon_pos[0] = mEnt->automapTransformed[0] - scissor->tl[0] + x - icon_size;
			icon_pos[1] = mEnt->automapTransformed[1] - scissor->tl[1] + y - icon_size;
		} else { 
			icon_pos[0] = x + mEnt->transformed[0] - icon_size;
			icon_pos[1] = y + mEnt->transformed[1] - icon_size;
			string_pos[0] = x + mEnt->transformed[0];
			string_pos[1] = y + mEnt->transformed[1] + icon_size;
		}

		icon_extends[0] = 2 * icon_size;
		icon_extends[1] = 2 * icon_size;
		if( scissor ) {
			icon_extends[0] *= (scissor->zoomFactor / 5.159);
			icon_extends[1] *= (scissor->zoomFactor / 5.159);
		}

		if( mEnt->type == ME_PLAYER_REVIVE ) {
			float msec;
			vec4_t reviveClr = { 1.f, 1.f, 1.f, 1.f };

			if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_AXIS) {
				msec = (cg_redlimbotime.integer - (cg.time%cg_redlimbotime.integer)) / (float)cg_redlimbotime.integer;
			} else if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_ALLIES) {
				msec = (cg_bluelimbotime.integer - (cg.time%cg_bluelimbotime.integer)) / (float)cg_bluelimbotime.integer;
			} else {
				msec = 0;
			}

			reviveClr[3] = .5f + .5f * ((sin(sqrt(msec) * 25 * 2 * M_PI) + 1) * .5f);

			trap_R_SetColor( reviveClr );
			CG_DrawPic( icon_pos[0] + 3, icon_pos[1] + 3, icon_extends[0] - 3, icon_extends[1] - 3, cgs.media.medicIcon);
			trap_R_SetColor( NULL );
		} else {
			if( cg.clientNum == mEnt->data ) {
				if( ci->ccSelected ) {
					trap_R_SetColor( colorRed );
				} else {
					trap_R_SetColor( colorYellow );
				}

				CG_DrawPic( icon_pos[0], icon_pos[1], icon_extends[0], icon_extends[1], cgs.media.ccPlayerHighlight);
				trap_R_SetColor( NULL );

				if(cg.predictedPlayerEntity.voiceChatSpriteTime > cg.time) {
					CG_DrawPic( icon_pos[0] + 12, icon_pos[1], icon_extends[0] * 0.5f, icon_extends[1] * 0.5f, cg.predictedPlayerEntity.voiceChatSprite);
				}
			} else if( mEnt->type == ME_PLAYER_DISGUISED ) {
				trap_R_SetColor( colorOrange );
				CG_DrawPic( icon_pos[0], icon_pos[1], icon_extends[0], icon_extends[1], cgs.media.ccPlayerHighlight);
				trap_R_SetColor( NULL );
			} else if( /*!(cgs.ccFilter & CC_FILTER_BUDDIES) &&*/ CG_IsOnSameFireteam( cg.clientNum, mEnt->data )) {
				if( ci->ccSelected ) {
					trap_R_SetColor( colorRed );
				}

				CG_DrawPic( icon_pos[0], icon_pos[1], icon_extends[0], icon_extends[1], cgs.media.ccPlayerHighlight);
				trap_R_SetColor( NULL );
			
				if( !scissor ) {
					CG_Text_Paint_Ext( string_pos[0], string_pos[1], 0.2f, 0.2f, colorWhite, ci->name, 0, 0, ITEM_TEXTSTYLE_SHADOWED, &cgs.media.limboFont2 );
//					CG_DrawStringExt_Shadow( string_pos[0], string_pos[1], ci->name, colorWhite, qfalse, 1, 8, 12, 0 );
				}

				if(cent->voiceChatSpriteTime > cg.time) {
					CG_DrawPic( icon_pos[0] + 12, icon_pos[1], icon_extends[0] * 0.5f, icon_extends[1] * 0.5f, cent->voiceChatSprite);
				}
			} else if( ci->team == snap->ps.persistant[PERS_TEAM] ) {
				if( ci->ccSelected ) {
					trap_R_SetColor( colorRed );
					CG_DrawPic( icon_pos[0], icon_pos[1], icon_extends[0], icon_extends[1], cgs.media.ccPlayerHighlight);
					trap_R_SetColor( NULL );
				}

				if(cent->voiceChatSpriteTime > cg.time) {
					CG_DrawPic( icon_pos[0] + 12, icon_pos[1], icon_extends[0] * 0.5f, icon_extends[1] * 0.5f,  cent->voiceChatSprite);
				}
			}

			c_clr[3] = 1.0f;

			trap_R_SetColor(c_clr);
			CG_DrawPic( icon_pos[0], icon_pos[1], icon_extends[0], icon_extends[1], classInfo->icon);

			CG_DrawRotatedPic( icon_pos[0]-1, icon_pos[1]-1, icon_extends[0]+2, icon_extends[1]+2, classInfo->arrow, (0.5 - ( mEnt->yaw - 180.f ) / 360.f));	
			trap_R_SetColor(NULL);
		}
		return;
	case ME_CONSTRUCT:
	case ME_DESTRUCT:
	case ME_DESTRUCT_2:
	case ME_TANK:
	case ME_TANK_DEAD:
	case ME_COMMANDMAP_MARKER:
		cent = NULL;
		if( mEnt->type == ME_TANK || mEnt->type == ME_TANK_DEAD ) {
			oidInfo = &cgs.oidInfo[ mEnt->data ];

			for( j = 0; j < cg.snap->numEntities; j++ ) {
				if( cg.snap->entities[j].eType == ET_OID_TRIGGER && cg.snap->entities[j].teamNum == mEnt->data ) {
					cent = &cg_entities[cg.snap->entities[j].number];
					if( !scissor ) {
						mEnt->transformed[0] = ((cent->lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w;
						mEnt->transformed[1] = ((cent->lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h;
					} else {
						mEnt->automapTransformed[0] = ((cent->lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w * scissor->zoomFactor;
						mEnt->automapTransformed[1] = ((cent->lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h * scissor->zoomFactor;
					}
					break;
				}
			}
		} else if( mEnt->type == ME_CONSTRUCT || mEnt->type == ME_DESTRUCT || mEnt->type == ME_DESTRUCT_2 ) {
			cent = &cg_entities[mEnt->data];

			oidInfo = &cgs.oidInfo[ cent->currentState.modelindex2 ];

			if( !scissor ) {
				mEnt->transformed[0] = ((cent->lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w;
				mEnt->transformed[1] = ((cent->lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h;
			} else {
				mEnt->automapTransformed[0] = ((cent->lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w * scissor->zoomFactor;
				mEnt->automapTransformed[1] = ((cent->lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h * scissor->zoomFactor;
			}
		} else if( mEnt->type == ME_COMMANDMAP_MARKER ) {
			oidInfo = &cgs.oidInfo[ mEnt->data ];

			if( !scissor ) {
				mEnt->transformed[0] = ((oidInfo->origin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w;
				mEnt->transformed[1] = ((oidInfo->origin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h;
			} else {
				mEnt->automapTransformed[0] = ((oidInfo->origin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w * scissor->zoomFactor;
				mEnt->automapTransformed[1] = ((oidInfo->origin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h * scissor->zoomFactor;
			}
		}

		// now check to see if the entity is within our clip region
		if( scissor && CG_ScissorEntIsCulled( mEnt, scissor ) ) {
			return;
		}

		if( cgs.ccLayers ) {
			if( CG_CurLayerForZ( mEnt->z ) != cgs.ccSelectedLayer )
                return;
		}

		if( oidInfo ) {
			customimage = mEnt->team == TEAM_AXIS ? oidInfo->customimageaxis : oidInfo->customimageallies;
		}

/*		if((mEnt->yaw & 0xFF) & (1 << (atoi(CG_ConfigString(mEnt->team == TEAM_AXIS ? CS_MAIN_AXIS_OBJECTIVE : CS_MAIN_ALLIES_OBJECTIVE)) - 1))) {
			trap_R_SetColor( colorYellow );
		}*/

		if(mEnt->type == ME_CONSTRUCT) {
			if(mEntFilter & CC_FILTER_CONSTRUCTIONS) {
				return;
			}
			pic = mEnt->team == TEAM_AXIS ? cgs.media.ccConstructIcon[0] : cgs.media.ccConstructIcon[1];
		} else if(mEnt->type == ME_TANK) {
			if(mEntFilter & CC_FILTER_OBJECTIVES) {
				return;
			}
			pic = cgs.media.ccTankIcon;
		} else if(mEnt->type == ME_TANK_DEAD) {
			if(mEntFilter & CC_FILTER_OBJECTIVES) {
				return;
			}
			pic = cgs.media.ccTankIcon;
			trap_R_SetColor( colorRed );
		} else if( mEnt->type == ME_COMMANDMAP_MARKER ) {
			pic = 0;
		} else if( mEnt->type == ME_DESTRUCT_2 ) {
			pic = 0;
		} else {
			if( mEntFilter & CC_FILTER_DESTRUCTIONS ) {
				return;
			}
			pic = mEnt->team == TEAM_AXIS ? cgs.media.ccDestructIcon[cent->currentState.effect1Time][0] : cgs.media.ccDestructIcon[cent->currentState.effect1Time][1];
		}

		{
			int info = 0;

			if( oidInfo ) {
				info = oidInfo->spawnflags;
			}

			if( info & (1 << 4) ) {
				if( mEntFilter & CC_FILTER_OBJECTIVES ) {
					return;
				}
			}
			if( info & (1 << 5) ) {
				if( mEntFilter & CC_FILTER_HACABINETS ) {
					return;
				}
			}
			if( info & (1 << 6) ) {
				if( mEnt->type == ME_DESTRUCT_2 ) {
					pic = mEnt->team == TEAM_AXIS ? cgs.media.ccCmdPost[0] : cgs.media.ccCmdPost[1];
				}
				if( mEntFilter & CC_FILTER_CMDPOST ) {
					return;
				}
			}
		}

		if( customimage ) {
			pic = customimage;
		}

		if( scissor ) {
			icon_pos[0] = mEnt->automapTransformed[0] - scissor->tl[0] + x;
			icon_pos[1] = mEnt->automapTransformed[1] - scissor->tl[1] + y;
		} else {
			icon_pos[0] = x + mEnt->transformed[0];
			icon_pos[1] = y + mEnt->transformed[1];
		}

#define CONST_ICON_NORMAL_SIZE 32.f
#define CONST_ICON_EXPANDED_SIZE 48.f

		if( interactive && !expanded && BG_RectContainsPoint( x + mEnt->transformed[0] - (CONST_ICON_NORMAL_SIZE*0.5f), y + mEnt->transformed[1] - (CONST_ICON_NORMAL_SIZE*0.5f), CONST_ICON_NORMAL_SIZE, CONST_ICON_NORMAL_SIZE, cgDC.cursorx, cgDC.cursory )) {
			float w;

			icon_extends[0] = CONST_ICON_EXPANDED_SIZE;
			icon_extends[1] = CONST_ICON_EXPANDED_SIZE;
			if( mEnt->type == ME_TANK_DEAD || mEnt->type == ME_TANK ) {
				icon_extends[1] *= 0.5f;
			}
			if( scissor ) {
				icon_extends[0] *= (scissor->zoomFactor / 5.159);
				icon_extends[1] *= (scissor->zoomFactor / 5.159);
			} else {
				icon_extends[0] *= cgs.ccZoomFactor;
				icon_extends[1] *= cgs.ccZoomFactor;
			}

			CG_DrawPic( icon_pos[0] - (icon_extends[0]*0.5f), icon_pos[1] - (icon_extends[1]*0.5f), icon_extends[0], icon_extends[1], pic );

			if( oidInfo ) {
				name = oidInfo->name;
			} else {
				name = va( "%i", j );
			}

			w = CG_Text_Width_Ext( name, 0.2f, 0, &cgs.media.limboFont2 );
			CG_CommandMap_SetHighlightText( name, icon_pos[0] - ( w * 0.5f ), icon_pos[1] - 8 );
		} else if ( interactive && (mEnt->yaw & 0xFF) & (1 << cgs.ccSelectedObjective) ) {
			float scalesize;
			int time = cg.time % 1400;

			if(time <= 700) {
				scalesize = 12 * (time) / 700.f;
			} else {
				scalesize = 12 * (1 - ((time - 700) / 700.f));
			}

			icon_extends[0] = CONST_ICON_NORMAL_SIZE + scalesize;
			icon_extends[1] = CONST_ICON_NORMAL_SIZE + scalesize;
			if( scissor ) {
				icon_extends[0] *= (scissor->zoomFactor / 5.159);
				icon_extends[1] *= (scissor->zoomFactor / 5.159);
			} else {
				icon_extends[0] *= cgs.ccZoomFactor;
				icon_extends[1] *= cgs.ccZoomFactor;
			}
			if( mEnt->type == ME_TANK_DEAD || mEnt->type == ME_TANK ) {
				icon_extends[1] *= 0.5f;
			}

			CG_DrawPic( icon_pos[0] - (icon_extends[0]*0.5f), icon_pos[1] - (icon_extends[1]*0.5f), icon_extends[0], icon_extends[1], pic );
		} else {
			icon_extends[0] = CONST_ICON_NORMAL_SIZE;
			icon_extends[1] = CONST_ICON_NORMAL_SIZE;
			if( mEnt->type == ME_TANK_DEAD || mEnt->type == ME_TANK ) {
				icon_extends[1] *= 0.5f;
			}
			if( scissor ) {
				icon_extends[0] *= (scissor->zoomFactor / 5.159);
				icon_extends[1] *= (scissor->zoomFactor / 5.159);
			} else {
				icon_extends[0] *= cgs.ccZoomFactor;
				icon_extends[1] *= cgs.ccZoomFactor;
			}

			CG_DrawPic( icon_pos[0] - (icon_extends[0]*0.5f), icon_pos[1] - (icon_extends[1]*0.5f), icon_extends[0], icon_extends[1], pic );
		}
		trap_R_SetColor( NULL );
		return;
	case ME_LANDMINE:
/*			if(mEntFilter & CC_FILTER_LANDMINES) {
			continue;
		}*/

		// now check to see if the entity is within our clip region
		if( scissor && CG_ScissorEntIsCulled( mEnt, scissor ) ) {
			return;
		}

		if( cgs.ccLayers ) {
			if( CG_CurLayerForZ( mEnt->z ) != cgs.ccSelectedLayer )
                return;
		}

		if( mEnt->data == TEAM_AXIS ) {
			pic = cgs.media.commandCentreAxisMineShader;
		} else { // TEAM_ALLIES
			pic = cgs.media.commandCentreAlliedMineShader;
		}			

		c_clr[3] = 1.0f;

		if( scissor ) {
			icon_pos[0] = mEnt->automapTransformed[0] - scissor->tl[0] + x;
			icon_pos[1] = mEnt->automapTransformed[1] - scissor->tl[1] + y;
		} else {
			icon_pos[0] = x + mEnt->transformed[0];
			icon_pos[1] = y + mEnt->transformed[1];
		}

		icon_extends[0] = 12;
		icon_extends[1] = 12;
		if( scissor ) {
			icon_extends[0] *= (scissor->zoomFactor / 5.159);
			icon_extends[1] *= (scissor->zoomFactor / 5.159);
		} else {
			icon_extends[0] *= cgs.ccZoomFactor;
			icon_extends[1] *= cgs.ccZoomFactor;
		}

		trap_R_SetColor(c_clr);
		CG_DrawPic( icon_pos[0] - icon_extends[0]*0.5f, icon_pos[1] - icon_extends[1]*0.5f, icon_extends[0], icon_extends[1], pic);
		trap_R_SetColor(NULL);

		j++;
		return;
	default:
		return;
	}
}

void CG_DrawMap( float x, float y, float w, float h, int mEntFilter, mapScissor_t *scissor, qboolean interactive, float alpha, qboolean borderblend ) {
	int i/*, j = 1*/;
	snapshot_t* snap;
//	vec4_t c_clr = {1.f, 1.f, 1.f, 1.f};
	mapEntityData_t* mEnt = &mapEntities[0];
	int icon_size;
	int exspawn;

	expanded = qfalse;

	if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) {
		snap = cg.nextSnap;
	} else {
		snap = cg.snap;
	}

	if ( scissor ) {
		float s0, s1, t0, t1;

		icon_size = AUTOMAP_PLAYER_ICON_SIZE;

		if ( scissor->br[0] >= scissor->tl[0] ) {
			float sc_x, sc_y, sc_w, sc_h;

			sc_x = x;
			sc_y = y;
			sc_w = w;
			sc_h = h;

			CG_DrawPic( sc_x, sc_y, sc_w, sc_h, cgs.media.commandCentreAutomapMaskShader );

			s0 = (scissor->tl[0])/(w*scissor->zoomFactor);
			s1 = (scissor->br[0])/(w*scissor->zoomFactor);
			t0 = (scissor->tl[1])/(h*scissor->zoomFactor);
			t1 = (scissor->br[1])/(h*scissor->zoomFactor);

			CG_AdjustFrom640( &sc_x, &sc_y, &sc_w, &sc_h );
			if( cgs.ccLayers ) {
				trap_R_DrawStretchPic( sc_x, sc_y, sc_w, sc_h, s0, t0, s1, t1, cgs.media.commandCentreAutomapShader[cgs.ccSelectedLayer] );
			} else {
				trap_R_DrawStretchPic( sc_x, sc_y, sc_w, sc_h, s0, t0, s1, t1, cgs.media.commandCentreAutomapShader[0] );
			}
			trap_R_DrawStretchPic( 0, 0, 0, 0, 0, 0, 0, 0, cgs.media.whiteShader ); // HACK : the code above seems to do weird things to 
																					// the next trap_R_DrawStretchPic issued. This works
																					// around this.
		}

		// Draw the grid
		CG_DrawGrid( x, y, w, h, scissor );
	} else {
		icon_size = COMMANDMAP_PLAYER_ICON_SIZE;

		{
			vec4_t color;
			Vector4Set( color, 1.f, 1.f, 1.f, alpha );
			trap_R_SetColor( color );
			if( cgs.ccLayers ) {
				CG_DrawPic(x, y, w, h, cgs.media.commandCentreMapShaderTrans[cgs.ccSelectedLayer] );
			} else {
				CG_DrawPic(x, y, w, h, cgs.media.commandCentreMapShaderTrans[0] );
			}
			trap_R_SetColor( NULL );
		}

		// Draw the grid
		CG_DrawGrid( x, y, w, h, NULL );
	}

	if( borderblend ) {
		vec4_t clr = { 0.f, 0.f, 0.f, 0.75f };
		trap_R_SetColor( clr );
		CG_DrawPic( x, y, w, h, cgs.media.limboBlendThingy );
		trap_R_SetColor( NULL );
	}

	exspawn = CG_DrawSpawnPointInfo( x, y, w, h, qfalse, scissor, -1 );

	for(i = 0, mEnt = &mapEntities[0]; i < mapEntityCount; i++, mEnt++ ) {
		if( mEnt->team != CG_LimboPanel_GetRealTeam() ) {
			continue;
		}

		if( mEnt->type == ME_PLAYER ||
			mEnt->type == ME_PLAYER_DISGUISED ||
			mEnt->type == ME_PLAYER_REVIVE )
			continue;

        CG_DrawMapEntity( mEnt, x, y, w, h, mEntFilter, scissor, interactive, snap, icon_size );
	}

	CG_DrawSpawnPointInfo( x, y, w, h, qtrue, scissor, exspawn );

	CG_DrawMortarMarker( x, y, w, h, qtrue, scissor, exspawn );

	for(i = 0, mEnt = &mapEntities[0]; i < mapEntityCount; i++, mEnt++ ) {
		if( mEnt->team != CG_LimboPanel_GetRealTeam() ) {
			continue;
		}

		if( mEnt->type != ME_PLAYER &&
			mEnt->type != ME_PLAYER_DISGUISED &&
			mEnt->type != ME_PLAYER_REVIVE )
			continue;

        CG_DrawMapEntity( mEnt, x, y, w, h, mEntFilter, scissor, interactive, snap, icon_size );
	}
}

void CG_DrawExpandedAutoMap( void ) {
	float x, y, w, h;
	float b_x, b_y, b_w, b_h;
	float s1, t1, s2, t2;
//	vec4_t colour = { 1.f, 1.f, 1.f, .5f };

	x = SCREEN_WIDTH + 10.f;
	y = 20.f;

	w = CC_2D_W;
	h = CC_2D_H;


	if( cgs.autoMapExpanded ) {	
		if( cg.time - cgs.autoMapExpandTime < 250.f ) {
			x -= ( ( cg.time - cgs.autoMapExpandTime ) / 250.f ) * ( w + 30.f );
		} else {
			x = SCREEN_WIDTH - w - 20.f;
		}
	} else {
		if( cg.time - cgs.autoMapExpandTime < 250.f ) {
			x = ( SCREEN_WIDTH - w - 20.f ) + ( ( cg.time - cgs.autoMapExpandTime ) / 250.f ) * ( w + 30.f );
		} else {
			return;
		}
	}

	CG_DrawMap( x, y, w, h, cgs.ccFilter, NULL, qfalse, .7f, qfalse );

	// Draw the border

	// top left
	s1 = 0;
	t1 = 0;
	s2 = 1;
	t2 = 1;
	b_x = x - 8;
	b_y = y - 8;
	b_w = 8;
	b_h = 8;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapCornerShader );

	// top
	s2 = w / 256.f;
	b_x = x;
	b_y = y - 8;
	b_w = w;
	b_h = 8;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapBorderShader );

	// top right
	s1 = 1;
	t1 = 0;
	s2 = 0;
	t2 = 1;
	b_x = x + w;
	b_y = y - 8;
	b_w = 8;
	b_h = 8;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapCornerShader );

	// right
	s1 = 1;
	t1 = h / 256.f;
	s2 = 0;
	t2 = 0;
	b_x = x + w;
	b_y = y;
	b_w = 8;
	b_h = h;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapBorder2Shader );

	// bottom right
	s1 = 1;
	t1 = 1;
	s2 = 0;
	t2 = 0;
	b_x = x + w;
	b_y = y + h;
	b_w = 8;
	b_h = 8;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapCornerShader );

	// bottom
	s1 = w / 256.f;
	b_x = x;
	b_y = y + h;
	b_w = w;
	b_h = 8;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapBorderShader );

	// bottom left
	s1 = 0;
	t1 = 1;
	s2 = 1;
	t2 = 0;
	b_x = x - 8;
	b_y = y + h;
	b_w = 8;
	b_h = 8;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapCornerShader );

	// left
	s1 = 0;
	t1 = 0;
	s2 = 1;
	t2 = h / 256.f;
	b_x = x - 8;
	b_y = y;
	b_w = 8;
	b_h = h;
	CG_AdjustFrom640( &b_x, &b_y, &b_w, &b_h );
	trap_R_DrawStretchPic( b_x, b_y, b_w, b_h, s1, t1, s2, t2, cgs.media.commandCentreAutomapBorder2Shader );
}

void CG_DrawAutoMap( void ) {
	float x, y, w, h;
	mapScissor_t mapScissor;
	vec2_t automapTransformed;

	memset( &mapScissor, 0, sizeof(mapScissor) );

	if( cgs.ccLayers ) {
		cgs.ccSelectedLayer = CG_CurLayerForZ( (int)cg.predictedPlayerEntity.lerpOrigin[2] );
	}

	x = 520;
	y = 20;
	w = 100;
	h = 100;

	if( cgs.autoMapExpanded ) {	
		if( cg.time - cgs.autoMapExpandTime < 100.f ) {
			y -= ( ( cg.time - cgs.autoMapExpandTime ) / 100.f ) * 128.f;
			CG_DrawExpandedAutoMap();
		} else {
			//y -= 128.f;
			CG_DrawExpandedAutoMap();
			return;
		}
	} else {
		if( cg.time - cgs.autoMapExpandTime <= 150.f ) {
			//y -= 128.f;
			CG_DrawExpandedAutoMap();
			return;
		} else if( ( cg.time - cgs.autoMapExpandTime > 150.f ) && ( cg.time - cgs.autoMapExpandTime < 250.f ) ) {
			y = ( y - 128.f ) + ( ( cg.time - cgs.autoMapExpandTime - 150.f ) / 100.f ) * 128.f;
			CG_DrawExpandedAutoMap();
		}
	}

	mapScissor.circular = qtrue;


	mapScissor.zoomFactor = automapZoom;

	mapScissor.tl[0] = mapScissor.tl[1] = 0;
	mapScissor.br[0] = mapScissor.br[1] = -1;

	automapTransformed[0] = ((cg.predictedPlayerEntity.lerpOrigin[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w * mapScissor.zoomFactor;
	automapTransformed[1] = ((cg.predictedPlayerEntity.lerpOrigin[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h * mapScissor.zoomFactor;

	// update clip region (for next drawing). clip region has a size kAutomap_width x kAutomap_height
	// and it is after zooming is accounted for.
	//
	// first try to center the clip region around the player. then make sure the region
	// stays within the world map.
	mapScissor.tl[0] = automapTransformed[0] - w/2;
	if( mapScissor.tl[0] < 0 )
		mapScissor.tl[0] = 0;
	mapScissor.br[0] = mapScissor.tl[0] + w;
	if( mapScissor.br[0] > (w * mapScissor.zoomFactor) ) {
		mapScissor.br[0] = w * mapScissor.zoomFactor;
		mapScissor.tl[0] = mapScissor.br[0] - w;
	}

	mapScissor.tl[1] = automapTransformed[1] - h/2;
	if( mapScissor.tl[1] < 0 )
		mapScissor.tl[1] = 0;
	mapScissor.br[1] = mapScissor.tl[1] + h;
	if ( mapScissor.br[1] > (h * mapScissor.zoomFactor)) {
		mapScissor.br[1] = h * mapScissor.zoomFactor;
		mapScissor.tl[1] = mapScissor.br[1] - h;
	}

	CG_DrawMap( x, y, w, h, cgs.ccFilter, &mapScissor, qfalse, 1.f, qfalse );
}

/*void CG_DrawWaypointInfo( int x, int y, int w, int h ) {
	snapshot_t	*snap;
	vec2_t		pos;
	int			i;

	if( cgs.ccFilter & CC_FILTER_WAYPOINTS ) {
		return;
	}

	if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) {
		snap = cg.nextSnap;
	} else {
		snap = cg.snap;
	}

	for ( i = 0; i < snap->numEntities; i++ ) {
		entityState_t *ent = &snap->entities[i];

		if ( ent->eType != ET_WAYPOINT )
			continue;

		// see if the waypoint owner is someone that you accept waypoints from
		if(!CG_IsOnSameFireteam( cg.clientNum, ent->clientNum )) {
			continue;
		}

		pos[0] = x + ((ent->pos.trBase[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * w;
		pos[1] = y + ((ent->pos.trBase[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * h;

		switch( ent->frame ) {
			case WAYP_ATTACK:	CG_DrawPic( pos[0] - 6, pos[1] - 6, 12, 12, cgs.media.waypointAttackShader ); break;
			case WAYP_DEFEND:	CG_DrawPic( pos[0] - 6, pos[1] - 6, 12, 12, cgs.media.waypointDefendShader ); break;
			case WAYP_REGROUP:	CG_DrawPic( pos[0] - 6, pos[1] - 6, 12, 12, cgs.media.waypointRegroupShader ); break;
		}
	}
}*/

int CG_DrawSpawnPointInfo( int px, int py, int pw, int ph, qboolean draw, mapScissor_t *scissor, int expand ) {
	int i;
	char buffer[64];
	vec2_t point;
	int e = -1;
	vec2_t icon_extends;

	team_t team = CG_LimboPanel_GetRealTeam();

	if( cgs.ccFilter & CC_FILTER_SPAWNS ) {
		return -1;
	}

#define FLAGSIZE_EXPANDED 48.f
#define FLAGSIZE_NORMAL 32.f
#define FLAG_LEFTFRAC (25/128.f)
#define FLAG_TOPFRAC (95/128.f)
#define SPAWN_SIZEUPTIME 1000.f
	for ( i = 1; i < cg.spawnCount; i++ ) {
		float changetime = 0;
		if(cg.spawnTeams_changeTime[i]) {
			changetime = (cg.time - cg.spawnTeams_changeTime[i]);
			if(changetime > SPAWN_SIZEUPTIME || changetime < 0) {
				changetime = cg.spawnTeams_changeTime[i] = 0;
			}
		}

		// rain - added parens around ambiguity
		if (((cgs.clientinfo[cg.clientNum].team != TEAM_SPECTATOR) &&
			(cg.spawnTeams[i] != team)) ||
			((cg.spawnTeams[i] & 256) && !changetime)) {

			continue;
		}

		if( cgs.ccLayers ) {
			if( CG_CurLayerForZ( (int)cg.spawnCoords[i][2] ) != cgs.ccSelectedLayer )
				break;
		}

		if( scissor ) {
			point[0] = ((cg.spawnCoordsUntransformed[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor;
			point[1] = ((cg.spawnCoordsUntransformed[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor;
		} else {
			point[0] = px + (((cg.spawnCoordsUntransformed[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw );
			point[1] = py + (((cg.spawnCoordsUntransformed[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph );
		}

		if( scissor && CG_ScissorPointIsCulled( point, scissor ) ) {
			continue;
		}

		if( scissor ) {
			point[0] += px - scissor->tl[0];
			point[1] += py - scissor->tl[1];
		}

		icon_extends[0] = FLAGSIZE_NORMAL;
		icon_extends[1] = FLAGSIZE_NORMAL;
		if( scissor ) {
			icon_extends[0] *= (scissor->zoomFactor / 5.159);
			icon_extends[1] *= (scissor->zoomFactor / 5.159);
		} else {
			icon_extends[0] *= cgs.ccZoomFactor;
			icon_extends[1] *= cgs.ccZoomFactor;
		}

		point[0] -= (icon_extends[0] * (39 / 128.f));
		point[1] += (icon_extends[1] * (31 / 128.f));

		if( changetime ) {
			if( draw ) {
				float size;

				if(cg.spawnTeams[i] == team) {
					size = 20 * (changetime / SPAWN_SIZEUPTIME);
				} else {
					size = 20 * (1 - (changetime / SPAWN_SIZEUPTIME));
				}

				if( scissor ) {
					size *= (scissor->zoomFactor / 5.159);
				} else {
					size *= cgs.ccZoomFactor;
				}

				CG_DrawPic( point[0] - FLAG_LEFTFRAC*size, point[1] - FLAG_TOPFRAC*size, size, size, cgs.media.commandCentreSpawnShader[  cg.spawnTeams[i] == TEAM_AXIS ? 0 : 1 ] );
			}
		} else if( (draw && i == expand) || (!expanded && BG_RectContainsPoint( point[0] - FLAGSIZE_NORMAL*0.5f, point[1] - FLAGSIZE_NORMAL*0.5f, FLAGSIZE_NORMAL, FLAGSIZE_NORMAL, cgDC.cursorx, cgDC.cursory )) ) {
			if( draw ) {
				float size = FLAGSIZE_EXPANDED;
				if( scissor ) {
					size *= (scissor->zoomFactor / 5.159);
				} else {
					size *= cgs.ccZoomFactor;
				}

				CG_DrawPic( point[0] - FLAG_LEFTFRAC*size, point[1] - FLAG_TOPFRAC*size, size, size, cgs.media.commandCentreSpawnShader[  cg.spawnTeams[i] == TEAM_AXIS ? 0 : 1 ] );
			} else {			
				if( !scissor ) {
					float w;

					Com_sprintf( buffer, sizeof( buffer ), "%s (Troops: %i)", cg.spawnPoints[i], cg.spawnPlayerCounts[i] );
					w = CG_Text_Width_Ext( buffer, 0.2f, 0, &cgs.media.limboFont2 );
					CG_CommandMap_SetHighlightText( buffer, point[0] - ( w * 0.5f ), point[1] - 8 );
				}

				e = i;
			}
		} else {
			if( draw ) {
				float size = FLAGSIZE_NORMAL;
				if( scissor ) {
					size *= (scissor->zoomFactor / 5.159);
				} else {
					size *= cgs.ccZoomFactor;
				}

				CG_DrawPic( point[0] - FLAG_LEFTFRAC*size, point[1] - FLAG_TOPFRAC*size, size, size, cgs.media.commandCentreSpawnShader[  cg.spawnTeams[i] == TEAM_AXIS ? 0 : 1 ] );
				
				if( !scissor ) {
					Com_sprintf( buffer, sizeof( buffer ), "(Troops: %i)", cg.spawnPlayerCounts[i] );
					CG_Text_Paint_Ext( point[0] + FLAGSIZE_NORMAL*0.25f, point[1], 0.2f, 0.2f, colorWhite, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED, &cgs.media.limboFont2 );
				}
			}
		}
	}

	return e;
}

void CG_DrawMortarMarker( int px, int py, int pw, int ph, qboolean draw, mapScissor_t *scissor, int expand ) {
	if( cg.lastFiredWeapon == WP_MORTAR_SET && cg.mortarImpactTime >= 0 ) {
		if( cg.snap->ps.weapon != WP_MORTAR_SET ) {
			cg.mortarImpactTime = 0;
		} else {

			//vec4_t colour = { .77f, .1f, .1f, 1.f };
			vec4_t colour = { 1.f, 1.f, 1.f, 1.f };
			vec3_t point;
//			int fadeTime = 0; // cg.time - (cg.predictedPlayerEntity.muzzleFlashTime + 5000);

			if( scissor ) {
				point[0] = ((cg.mortarImpactPos[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor;
				point[1] = ((cg.mortarImpactPos[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor;
			} else {
				point[0] = px + (((cg.mortarImpactPos[0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw );
				point[1] = py + (((cg.mortarImpactPos[1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph );
			}

			// rain - don't return if the marker is culled, just don't
			// draw it.
			if (!(scissor && CG_ScissorPointIsCulled( point, scissor ))) {
				if( scissor ) {
					point[0] += px - scissor->tl[0];
					point[1] += py - scissor->tl[1];
				}

				if( cg.mortarImpactOutOfMap ) {
					if( !scissor ) {
						// near the edge of the map, fit into it
						if( point[0] + 8.f > (px + pw) )
							point[0] -= 8.f;
						else if( point[0] - 8.f < px )
							point[0] += 8.f;

						if( point[1] + 8.f > (py + ph) )
							point[1] -= 8.f;
						else if( point[1] - 8.f < py )
							point[1] += 8.f;
					}
					colour[3] = .5f;
				}

				trap_R_SetColor( colour );
				CG_DrawRotatedPic( point[0] - 8.f, point[1] - 8.f, 16, 16, cgs.media.ccMortarHit, .5f - ( cg.mortarFireAngles[YAW] /*- 180.f */+ 45.f ) / 360.f );
				trap_R_SetColor( NULL );
			}
		}
	}

	if( COM_BitCheck( cg.snap->ps.weapons, WP_MORTAR_SET ) ) {
		int i;

		for( i = 0; i < MAX_CLIENTS; i++ ) {
			//vec4_t colour = { .23f, 1.f, .23f, 1.f };
			vec4_t colour = { 1.f, 1.f, 1.f, 1.f };
			vec3_t point;
			int fadeTime = cg.time - (cg.artilleryRequestTime[i] + 25000);

			if( fadeTime < 5000 ) {
				if( fadeTime > 0 ) {
					colour[3] = 1.f - (fadeTime/5000.f);
				}

				if( scissor ) {
					point[0] = ((cg.artilleryRequestPos[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw * scissor->zoomFactor;
					point[1] = ((cg.artilleryRequestPos[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph * scissor->zoomFactor;
				} else {
					point[0] = px + (((cg.artilleryRequestPos[i][0] - cg.mapcoordsMins[0]) * cg.mapcoordsScale[0]) * pw );
					point[1] = py + (((cg.artilleryRequestPos[i][1] - cg.mapcoordsMins[1]) * cg.mapcoordsScale[1]) * ph );
				}

				// rain - don't return if the marker is culled, just skip
				// it (so we draw the rest, if any)
				if( scissor && CG_ScissorPointIsCulled( point, scissor ) ) {
					continue;
				}

				if( scissor ) {
					point[0] += px - scissor->tl[0];
					point[1] += py - scissor->tl[1];
				}

				trap_R_SetColor( colour );
				CG_DrawPic( point[0] - 8.f, point[1] - 8.f, 16, 16, cgs.media.ccMortarTarget );
				trap_R_SetColor( NULL );

				//CG_FillRect( point[0] - 8.f, point[1] - 8.f, 16, 16, colour );
			}
		}
	}
}

/*void CG_DrawCommandCentreLayers( void ) {
	int x, y;
	int i;
	char *s;

	if( !cgs.ccLayers )
		return;

	x = CC_2D_X + CC_2D_W - 32; 
	y = CC_2D_Y + CC_2D_H - 32;

	for( i = 0; i < cgs.ccLayers; i++ ) {
		if( i == cgs.ccSelectedLayer )
			CG_FillRect( x, y, 32, 32, clrBrownTextLt ); 
		else
			CG_FillRect( x, y, 32, 32, clrBrownText ); 
		CG_DrawRect( x, y, 32, 32, 1, colorBlack );

		if( i == 0 )
			s = "G";
		else
			s =  va( "%i", i );

		CG_Text_Paint( x + 1 + ( ( 32 - CG_Text_Width( s, .5f, 0 ) ) * .5f ),
					   y + 16 +( ( 32 - CG_Text_Height( s, .5f, 0 ) ) *.5f ),
					   .5f, clrBrownTextDk, s, 0, 0, 0 );
		y -= 34;
	}
}*/

mapEntityData_t* CG_ScanForCommandCentreEntity( void ) {
	vec_t	rangeSquared = Square(1000);
	int		ent = 0;
	mapEntityData_t* mEnt = &mapEntities[0];
	int i;

	if( mapEntityCount <= 0 ) {
		return NULL;
	}

	for(i = 0; i < mapEntityCount; i++, mEnt++ ) {
		float rngSquared;

		if( cgs.ccLayers ) {
			if( CG_CurLayerForZ( mEnt->z ) != cgs.ccSelectedLayer )
                continue;
		}

		rngSquared = Square(CC_2D_X + mEnt->transformed[0] - cgDC.cursorx) + Square(CC_2D_Y + mEnt->transformed[1] - cgDC.cursory);

		if( i == 0 || rngSquared < rangeSquared ) {
			rangeSquared = rngSquared;
			ent = i;
		}
	}

	if( rangeSquared < Square(8)) {
		return &mapEntities[ent];
	}
	return NULL;
}

typedef enum {
	MT_CONSTRUCT,
	MT_CONSTRUCT_BARE,
	MT_DESTRUCT,
	MT_DESTRUCT_BARE,
	MT_TANK_BARE,
	MT_PLAYER,
	MT_INFO
} menuType_t;

qboolean CG_PlayerSelected( void ) {
	snapshot_t* snap;
	int i;

	if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) {
		snap = cg.nextSnap;
	} else {
		snap = cg.snap;
	}

	for( i = 0; i < MAX_CLIENTS; i++ ) {
		if( cgs.clientinfo[i].team == snap->ps.persistant[PERS_TEAM] ) {
			if( cgs.clientinfo[i].ccSelected ) {
				return qtrue;
			}
		}
	}
	return qfalse;
}

#define CC_MENU_WIDTH 150

qboolean CG_CommandCentreLayersClick( void ) {
	int x, y;
	int i;

	if( !cgs.ccLayers )
		return qfalse;

	x = CC_2D_X + CC_2D_W - 32; 
	y = CC_2D_Y + CC_2D_H - 32;

	for( i = 0; i < cgs.ccLayers; i++ ) {
		if( BG_RectContainsPoint( x, y, 32, 32, cgDC.cursorx, cgDC.cursory ) ) {
			cgs.ccSelectedLayer = i;
			return qtrue;
		}
		y -= 34;
	}

	return qfalse;
}

qboolean CG_CommandCentreSpawnPointClick( void ) {
	int i;
	vec2_t point;

	if( cgs.ccFilter & CC_FILTER_SPAWNS ) {
		return qfalse;
	}

	for ( i = 1; i < cg.spawnCount; i++ ) {
		if( (cgs.clientinfo[cg.clientNum].team != TEAM_SPECTATOR) && cg.spawnTeams[i] && cg.spawnTeams[i] != CG_LimboPanel_GetRealTeam())
			continue;

		if( cg.spawnTeams[i] & 256 )
			continue;

		if( cgs.ccLayers ) {
			if( CG_CurLayerForZ( (int)cg.spawnCoords[i][2] ) != cgs.ccSelectedLayer )
                continue;
		}

		point[0] = cg.spawnCoords[i][0];
		point[1] = cg.spawnCoords[i][1];

		if( BG_RectContainsPoint( point[0] - FLAGSIZE_NORMAL*0.5f, point[1] - FLAGSIZE_NORMAL*0.5f, FLAGSIZE_NORMAL, FLAGSIZE_NORMAL, cgDC.cursorx, cgDC.cursory ) ) {
			trap_SendConsoleCommand( va( "setspawnpt %i\n", i ) );
			cg.selectedSpawnPoint = i;
			cgs.ccRequestedObjective = -1;
			return qtrue;
		}
	}

	return qfalse;
}

void CG_CommandCentreClick( int key ) {
	switch( key ) {
		case K_MOUSE1:
			if( CG_CommandCentreSpawnPointClick() ) {
				return;
			}
			break;
	}
}

char		cg_highlightText[256];
rectDef_t	cg_highlightTextRect;
void CG_CommandMap_SetHighlightText( const char* text, float x, float y ) {
	Q_strncpyz( cg_highlightText, text, sizeof( cg_highlightText ) );
	cg_highlightTextRect.x = x;
	cg_highlightTextRect.y = y;
	expanded = qtrue;
}

void CG_CommandMap_DrawHighlightText( void ) {
	CG_Text_Paint_Ext( cg_highlightTextRect.x, cg_highlightTextRect.y, 0.25f, 0.25f, colorWhite, cg_highlightText, 0, 0, ITEM_TEXTSTYLE_SHADOWED, &cgs.media.limboFont2 );
	*cg_highlightText = '\0';
}
